//use closure to clean inner variable

clean_str2plain = function () {};
clean_saltPlain = function () {};
clean_plain2str = function () {};
clean_desaltPlain = function () {};
clean_passwd2key_16 = function () {};
clean_passwd2key_32 = function () {};
clean_AegisEncrypt = function () {};
clean_AegisDecrypt = function () {};

function cleanInternel () {
	clean_str2plain();
	clean_saltPlain();
	clean_plain2str();
	clean_desaltPlain();
	clean_passwd2key_16();
	clean_passwd2key_32();
	clean_AegisEncrypt();
	clean_AegisDecrypt();

	clean_str2plain = function () {};
	clean_saltPlain = function () {};
	clean_plain2str = function () {};
	clean_desaltPlain = function () {};
	clean_passwd2key_16 = function () {};
	clean_passwd2key_32 = function () {};
	clean_AegisEncrypt = function () {};
	clean_AegisDecrypt = function () {};
}

function str2plain (s) { //Use UTF-8 Encode
	var plain = new Array();
	var i = 0, j = 0;
	for (i = 0, j = 0; i < s.length; i++, j++) {
		var charCode;
		charCode = s.charCodeAt(i);
		if (charCode < 0x80) { 
			plain[j] = charCode;
		} else if (charCode < 0x800) {
			plain[j] = Math.floor(charCode / 0x40) + 0xC0;
			j++;
			plain[j] = charCode % 0x40 + 0x80;
		} else if (charCode < 0x10000) {
			plain[j] = Math.floor(charCode / (0x1000)) + 0xE0;
			j++;
			plain[j] = Math.floor(charCode / 0x40) % 0x40 + 0x80;
			j++;
			plain[j] = charCode % 0x40 + 0x80;
		} else {
			plain[j] = Math.floor(charCode / 0x40000) + 0xF0;
			j++;
			plain[j] = Math.floor(charCode % 0x40000 / 0x1000) + 0x80;
			j++;
			plain[j] = Math.floor(charCode % 0x1000 / 0x40) + 0x80;
			j++;
			plain[j] = charCode % 0x40 + 0x80;
		}
		charCode = 0;
	}
	i = 0;
	j = 0;
	s = "";
	clean_str2plain = function () {
		plain=[];
	};
	return plain;
}

function saltPlain (p) {
	var saltLen = 0;
	var saltedPlain = new Array();
	var i = 0;
	saltLen = 16 - p.length;
	saltedPlain[0]=saltLen;
	for (i = 1; i < saltLen; i++) {
		saltedPlain[i] = Math.floor(Math.random()*94.99+33);
	}
	for (i = 0; i < p.length; i++) {
		saltedPlain[i + saltLen] = p[i];
	}
	saltLen = 0;
	p = [];
	clean_saltPlain = function () {
		saltedPlain = [];
	};
	return saltedPlain;
}

function chiper2hex (c) {
	var hex = new Array();
	var i = 0;
	for (i = 0; i < c.length; i++) {
		hex[i] = c[i].toString(16);
		if (hex[i].length < 2) {
			hex[i] = "0" + hex[i];
		}
	}
	return hex.join("");
}

function hex2chiper (h) {
	var c = new Array();
	var i = 0;
	for (i = 0; i*2 < h.length; i++) {
		c[i] = parseInt(h[i * 2]+h[i * 2 + 1], 16);
	}
	return c;
}

function desaltPlain (sa) {
	var plain = new Array();
	var saltLen = 0;
	var i = 0;
	var AT = function (j) {
		return j + saltLen;
	}
	saltLen = sa[0];
	for (i = 0; AT(i) < sa.length; i++) {
		plain[i] = sa[AT(i)];
	}
	saltLen = 0;
	sa = [];
	AT = function () {};
	clean_desaltPlain = function () {
		plain = [];
	};
	return plain;
}

function plain2str (p) {
	var i = 0;
	var s = new Array();
	for (i = 0, j = 0; j < p.length; i++, j++) {
		if (p[j] < 0x80) {
			s[i] = String.fromCharCode(p[j]);
		} else if (p[j] < 0xE0) {
			var charCode;
			charCode = (p[j] - 0xC0) * 0x40 + p[j + 1] - 0x80;
			j++;
			s[i] = String.fromCharCode(charCode);
		} else if (p[i] < 0xF0) {
			var charCode;
			charCode = (p[j] - 0xE0) * 0x1000 + (p[j + 1] - 0x80) * 0x40 + p[j + 2] -0x80;
			j += 2;
			s[i] = String.fromCharCode(charCode);
		} else {
			var charCode;
			charCode = (p[j] - 0xF0) * 0x40000 + (p[j + 1] - 0x80) * 0x1000 + (p[j + 2] - 0x80) * 0x40 + p[j + 3] -0x80;
			j += 3;
			s[i] = String.fromCharCode(charCode);
		}
	}
	i = 0;
	p = [];
	clean_plain2str = function () {
		s = [];
	};
	return s.join("");
}

function passwd2key_16 (passwd) {
	var key = new Array();
	var i = 0;
	for (i = 0; i < 16; i++) { 
		if (i < passwd.length) {
			key[i] = passwd.charCodeAt(i);
		} else {
			key[i] = 0;
		}
	}
	i = 0;
	passwd = "";
	clean_passwd2key_16 = function () {
		key = [];
	};
	return key;
}

function passwd2key_32 (passwd) {
	var key = new Array();
	var i = 0;
	for (i = 0; i < 32; i++) { 
		if (i < passwd.length) {
			key[i] = passwd.charCodeAt(i);
		} else {
			key[i] = 0;
		}
	}
	i = 0;
	passwd = "";
	clean_passwd2key_32 = function () {
		key = [];
	};
	return key;
}

function AegisEncrypt(content, passwd) {
	var key;
	var tmp;
	var res = "";
	var i;
	if (passwd.length > 16) {
		key = passwd2key_32(passwd);
	} else {
		key = passwd2key_16(passwd);
	}
	AES_Init();
	AES_ExpandKey(key);
	for (i = 0; i * 12 < content.length; i++) {
		tmp = saltPlain(str2plain(content.substring(i * 12, (i + 1) * 12)));
		AES_Encrypt(tmp, key);
		res = res + chiper2hex(tmp);
	}
	AES_Done();
	content = null;
	key = null;
	passwd = null;
	tmp = null;
	clean_AegisEncrypt = function () {
		res = null;
	};
	i = 0;
	return res;
};

function AegisDecrypt(content, passwd) {
	var key;
	var tmp;
	var res = "";
	var i;
	if (passwd.length > 16) {
		key = passwd2key_32(passwd);
	} else {
		key = passwd2key_16(passwd);
	}
	AES_Init();
	AES_ExpandKey(key);
	for (i = 0; i * 32 < content.length; i++) {
		tmp = hex2chiper(content.substring(i * 32, (i + 1) * 32));
		AES_Decrypt(tmp, key);
		res = res + plain2str(desaltPlain(tmp));
	}
	AES_Done();
	content = null;
	clean_AegisDecrypt = function () {
		res = null;
	};
	key = null;
	passwd = null;
	tmp = null;
	i = 0;
	return res;
};
